package org.gen.core;

import freemarker.template.Template;
import org.gen.config.GenConfig;
import org.gen.util.DBMetaUtil;
import org.gen.util.MavenModuleUtil;

import java.io.*;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author 朱良才
 * @Email zhuliangcai@itcast.com
 * @Date 2017-10-16
 */
public abstract class Generate {
    public static final Map<String, Object> root = GenConfig.configPersonal();
    public static final String moduleRootPath = MavenModuleUtil.getModuleRootPath();
    public void start() {
        try {
            //获取数据库源数据
            DatabaseMetaData metaData = DBMetaUtil.getMetaData();
            /**
             * 其中"%"就是表示*的意思，也就是任意所有的意思。
             * 其中m_TableName就是要获取的数据表的名字，
             * 如果想获取所有的表的名字，就可以使用"%"来作为参数了。
             * 获取数据库中所有表的源数据信息
             */
            ResultSet tableRet = metaData.getTables(null, "%", "%", new String[]{"TABLE"});
            //提取表的名字。
            List<Attribute> attr_list = new ArrayList<>();
            while (tableRet.next()) {
                String TABLE_NAME = tableRet.getString("TABLE_NAME");
                //将当前表的数据放到表字段属性容器中
                putTableToList(metaData, TABLE_NAME, attr_list);
                //生成当前表的pojo
                rebuildConfigRoot(TABLE_NAME, attr_list);
                //attr_list 表字段属性容器，用完即清空
                gen();
                attr_list.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("未知异常" + e.getMessage());
        }

    }

    protected abstract void rebuildConfigRoot(String table_name, List<Attribute> attr_list);

    protected abstract void gen() throws Exception;
    public void commonGenerateFile(String packageDir ,String fileName,Template template){
        commonGenerateFile(packageDir, fileName, template,false);//true mean test code,false mean normal code
    }
    public void commonGenerateFile(String packageDir ,String fileName,Template template,boolean isTest) {
        try {
            String dirStr ;
            if(isTest){
                dirStr ="test";
            }else{
                dirStr ="main";
            }
            File dir = new File(moduleRootPath + "/src/"+dirStr+"/java/" + packageDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            OutputStream fos = new FileOutputStream(new File(dir, fileName)); //java文件的生成目录
            Writer out = new OutputStreamWriter(fos);
            template.process(root,out);
            fos.flush();
            fos.close();
            System.out.println("generated "+ fileName+ " code success!");
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("commonGenerateFile输出异常 :"+e.getMessage());
        }

    }
    //字符串首字母转小写
    public String UncapFirstString(String str){
        return str.substring(0,1).toLowerCase()+str.substring(1);
    }
    //包名转换为路径
    public String packageToDir(String packageName) {
        String[] split = packageName.split("\\.");
        StringBuilder ret = new StringBuilder();
        for (String str : split) {
            ret.append(str).append("/");
        }
        return ret.toString();
    }


    //把表数据放到集合中
    public void putTableToList(DatabaseMetaData dbmd, String m_TableName, List<Attribute> attr_list){
        try {
            String columnName;
            String columnType;
            ResultSet colRet = dbmd.getColumns(null, "%", m_TableName, "%");
            while (colRet.next()) {
                columnName = colRet.getString("COLUMN_NAME");
                columnType = colRet.getString("TYPE_NAME");
                attr_list.add(new Attribute(columnName,columnNameToJavaProperty(columnName), jdbcTypeToJavaType(columnType)));
                //System.out.println(columnName + " " + columnType);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    //    判断是否包含日期
    protected boolean hasDateType(List<Attribute> attr_list) {
        for (Attribute attr : attr_list) {
            if ("Date".equals(attr.getType())) {
                return true;
            }
        }
        return false;
    }

    //    将表名转换为java类名，规则即去掉下划线，将首字符大写
    protected String tableNameToClassName(String tablename) {
        String[] split = tablename.split("_");
        StringBuilder ret = new StringBuilder();
        for (String str : split) {
//            if("tb".equals(str)){
//                continue;
//            }
            //首字母变大写
            str = str.substring(0, 1).toUpperCase() + str.substring(1);
            //拼接到一起作为类名
            ret.append(str);
        }
        return ret.toString();
    }

    //将列名转换为java属性名，规则即去掉下划线，将第一个单词全小写,其他每个单词首字符大写，
    protected static String columnNameToJavaProperty(String columnName) {
//        province_id
        String[] split = columnName.split("_");
        StringBuilder ret = new StringBuilder();
        for (String str : split) {
            //首字母变大写
            str = str.substring(0, 1).toUpperCase() + str.substring(1);
            //拼接到一起作为类名
            ret.append(str);
        }
        String javaProperty = ret.toString();
        return javaProperty.substring(0, 1).toLowerCase() + javaProperty.substring(1);

    }

    //数据库类型和java类型的转换
    protected String jdbcTypeToJavaType(String jdbcType) {
        String javaType = mysqlDict().get(jdbcType.toUpperCase());
        if(javaType==null ||javaType.trim()=="") {
            javaType = "String";
        }
        return javaType;
    }

    private static Map<String, String> mysqlDict(){
        Map<String, String> dict = new HashMap<>();
        dict.put("VARCHAR", "String");
        dict.put("BIGINT", "Long");
        dict.put("VARCHAR", "String");
        dict.put("INT", "Integer");
        dict.put("DECIMAL", "Double");
        dict.put("DATETIME", "Date");
        return dict;
    }

}